package com.lichao.FinkDataProcess.sink;

import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import java.io.BufferedWriter;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;

public class DynamicCompilerLoader {

    // 编译源代码字符串并返回编译后的类文件路径
    public static Path compile(String sourceCode, String className) throws IOException {
        // 使用系统临时目录
        Path tempDir = Files.createTempDirectory("DynamicCompiler");
        Path sourceFile = tempDir.resolve(className + ".java");
        Path classFile = tempDir.resolve(className + ".class");

        // 将源代码写入临时文件
        try (BufferedWriter writer = Files.newBufferedWriter(sourceFile)) {
            writer.write(sourceCode);
        }

        // 使用JavaCompiler编译源代码文件
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        int compilationResult = compiler.run(null, null, null, sourceFile.toFile().getPath());
        if (compilationResult != 0) {
            throw new RuntimeException("Compilation Failed for source: " + sourceCode);
        }

        // 返回编译后的类文件路径
        return classFile;
    }

    // 加载编译后的类并返回Class对象
    public static Class<?> loadClass(String className, Path classFilePath) throws Exception {
        // 将类文件转换为URL
        URL classUrl = classFilePath.toUri().toURL();
        URLClassLoader classLoader = new URLClassLoader(new URL[]{classUrl});

        try {
            // 加载类并返回
            return classLoader.loadClass(className);
        } finally {
            // 关闭类加载器（注意：在某些JVM实现中，这可能不是必需的或可能无效）
            classLoader.close();
        }
    }

    // 测试动态编译和加载
    public static void main(String[] args) {
        try {
            // 示例源代码字符串
            String sourceCode = "public class HelloWorld1 {" +
                    "    public void sayHello() {" +
                    "        System.out.println(\"Hello, World!\");" +
                    "    }" +
                    "}";

            // 编译源代码
            String className = "HelloWorld1";
            Path classFilePath = compile(sourceCode, className);

            // 检查类文件是否存在
            if (!Files.exists(classFilePath)) {
                throw new RuntimeException("Class file not found at: " + classFilePath);
            }

            // 加载编译后的类
            Class<?> helloWorldClass = loadClass(className, classFilePath);

            // 创建类的实例并调用方法
            Object helloWorldInstance = helloWorldClass.getDeclaredConstructor().newInstance();
            Method sayHelloMethod = helloWorldClass.getMethod("sayHello");
            sayHelloMethod.invoke(helloWorldInstance);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}